'''
class
'''
import re
import xml.etree.ElementTree as ET

class myXML:
    """
    element: change property value, add propery, remove propery
    element: delete child,add child
    element: find parent, find all children
    tree:print whole tree, search key value,search element, search key
    #to fix the issue of 1.how write/read comments in xml,2.encoding,3.align
    """
    def __init__(self, inXMLFile):
        self.myXML=inXMLFile
        self.tree=ET.ElementTree()
        self.root=None
    def setXMLFile(self,inXMLFile):
        self.myXML=inXMLFile
    def openXML(self):        
        self.tree=ET.parse(self.myXML)
        self.root=self.tree.getroot()
    def printElementInfo(self, inElement, level=0):
        leftMargin=' '*level*2
        print leftMargin+"Element:" + inElement.tag
        for sname in inElement.keys():
            print leftMargin+'| '+sname+":"+inElement.attrib[sname]        
    def printChildInfo(self, inElement,level=0):
        #print inElement.tag+' '+inElement.attrib['Name']#hard code for attrib name will raise Exception, while for jv's xml, name property is required
        leftMargin=' '*level*2
        for ElemChild in inElement.getchildren():
            print leftMargin+"|->Child:" + ElemChild.tag
            for sname in ElemChild.keys():
                print leftMargin+'|'+'| '+sname+": "+ElemChild.attrib[sname]
    def printWholeTree(self,inElement,level=0, withProp=False):
        if inElement==None: #if inElement is None
            return
        leftMargin=' '*level*2
        print leftMargin+"|->level" +str(level)+ ":" + inElement.tag,
        if 'Name' in inElement.keys():
            print inElement.attrib['Name']
        else:
            print ''
        if withProp:
            for sname in inElement.keys():
                print leftMargin+' *'+sname+":"+inElement.attrib[sname]
        level=level+1
        for ElemChild in inElement.getchildren():
            self.printWholeTree(ElemChild, level,withProp)
    def findbyElement(self,inElemName):#todo return
        for l in self.root.iter(inElemName):
            self.printElementInfo(l)
    def findbyKey(self, inKeyName, inElement=None):#todo return
        if inElement is None:
            inElement=self.root
        for key in inElement.keys():
            if re.match('.*'+inKeyName+'.*',key):
                self.printElementInfo(inElement)
                break
        for c in inElement.getchildren():
            self.findbyKey(inKeyName,c)
    def findbyValue(self,inValue,inElement=None,isReg=False):
        rslt=None
        if inElement is None:
            inElement=self.root
        if isReg:
            sMatch=inValue
        else:
            sMatch='.*'+inValue+'.*'
        for key in inElement.keys():
            if re.match(sMatch,inElement.attrib[key]):
                self.printElementInfo(inElement)
                rslt.append(inElement)
                break
        for c in inElement.getchildren():
            rslt.append(self.findbyValue(inValue,c))
        return rslt
    def findbyKeyValue(self,inKey,inValue,inElement=None):#todo
        rslt=None
        if inElement is None:
            inElement=self.root
        if inKey in inElement.keys():
            if re.match('.*'+inValue+'.*',inElement.attrib[inKey]):
                self.printElementInfo(inElement)
                rslt.append(inElement)
        for c in inElement.getchildren():
            rslt.append(self.findbyKeyValue(inKey,inValue,c))
        return rslt        
    def findParent(self,inElement,parNode=None):
        """
            test script:
            x=myXML('d:/tmp/py/xml.xml')
            x.openXML()            
            e=x.root.find('./*/*/Pub_Ref')
            x.findParent(e)
        """
        par=None
        if parNode is None: parNode =self.root
        for l in parNode.getchildren():
            if l == inElement:
                par=parNode
        if par is None:
            for l in parNode.getchildren():
                par = self.findParent(inElement,l)
        if par is not None:
            print "Parent:"
            self.printElementInfo(par)
            print "Child:"
            self.printElementInfo(inElement)
            return par
        else:
            print "Can't find parent"
            print "Child:"
            self.printElementInfo(inElement)
            return par
    def removeChildbyTag(self, inChildTag,inElement=None):
        if inElement is None:
            inElement=self.root
        for l in inElement.findall(inChildTag):
            inElement.remove(l)
        for l in inElement:
            self.removeChildbyTag(inChildTag,l)
        self.tree.write(self.myXML+'.xml')            
    def removeChildbyName(self, inChildName,inElement=None):
        if inElement is None:
            inElement=self.root
        ls=inElement.findall('./*[@Name="{0}"]'.format(inChildName))
        for l in ls:
            inElement.remove(l)
        for c in inElement:
            self.removeChildbyName(inChildName,c)
        self.tree.write(self.myXML+'.xml')
    def removeChildbyNameReg(self,inChildNameReg,inElement=None):
        clist=[]
        if inElement is None:
            inElement=self.root
        for c in inElement:
            if 'Name' in c.keys():
                if re.match(inChildNameReg,c.attrib['Name']):
                    clist.append(c)
        for l in clist:
            inElement.remove(l)
        for c in inElement:
            self.removeChildbyNameReg(inChildNameReg,c)
        self.tree.write(self.myXML+'.xml')            
    def removeChildAll(self, inElement):
        #Element.clear()will remove all children and element's properties
        #for l in inElement.getchildren():#getchildren() is deprecated  by list(elem) or iteration
        #for l in inElement:has issue to remove subElement,1st remove,2nd pased
        for i in range(len(inElement)):
            inElement.remove(inElement[0])
        self.tree.write(self.myXML+'.xml')        
    def addChild(self,parElement,tag):
        el=ET.SubElement(parElement,tag)
        self.tree.write(self.myXML+'.xml')
        return el
    def copyChild(self,parElement,cElement,newName):
        #append(subelement): Adds the element subelement to the end of this elements 
        #extend(subelements) for muliple subElement
        #insert(index, element):Inserts a subelement at the given position in this element
        myE=cElement
        #parElement.append(myE)#will not change into new line
        el=ET.SubElement(parElement,myE.tag)
        el.set('Name',newName)
        self.tree.write(self.myXML+'.xml')
        return el
    def addPropty(self,inElement,inProp,inValue=""):
        inElement.set(inProp,inValue)
        self.tree.write(self.myXML+'.xml')
    def removePropty(self,inElement,inProp):
        for inKey in inElement.keys():
            if inKey == inProp:
                del inElement.attrib[inKey]                
        self.tree.write(self.myXML+'.xml')
    def ChgPropty(self,inElement,inProp,inValue=""):
        inElement.set(inProp,inValue)
        self.tree.write(self.myXML+'.xml')

####test xml######

from myXML import myXML
import xml.etree.ElementTree as ET
##tree=ET.parse('d:/tmp/py/xml.xml')
##root=tree.getroot()
##ET.SubElement(root,'MyTest')
##ET.SubElement(root,'MyTest2')
##tree.write('d:/tmp/py/xml.xml.xml')
##for l in root.findall('Pub_Ref'):# can just find the direct child
##    print l.tag
##for l in root.iter('DP'):
##    print l.tag
##for l in root.iter():
##    print l.tag

x=myXML('d:/tmp/py/xml.xml')
x.openXML()
##x.findbyElement('DP')
##x.findbyValue('_TX$',isReg=True)
##e=x.root.find('./*/*/Pub_Ref')
##x.findParent(e)
##x.removeChildbyNameReg(".*DLS_to_DLP_Control_Parameter.*")
e=x.root[1]
##x.removeChildAll(e)
ec=x.addChild(e,'PHText')
x.addPropty(ec,'Name','ph')
ec2=x.copyChild(e,ec,'PHTest')
x.addPropty(ec2,'Type','ph2')
x.ChgPropty(ec2,'Type','ph2nd')
x.addPropty(ec2,'Type222','ph2')
x.removePropty(ec2,'Type222')



##e=root[1]
##print e.tag, e.attrib['Name']
##for c in e.getchildren():
##    l=c
##    break
##p=l.findall('.')
##if p is not None:    print p
##pp=e.findall('.A653QueuingPort/Ep_Ref')
##if pp is not None: print pp
##for l in root.findall('./*/*/DS/..'):
##    print l.tag

##e=root[1]
##for i in ET.tostringlist(e):
##    print i

